import { _decorator, Component, Node, v3, Vec3, RigidBody2D, v2, Vec2, clamp, Sprite, tween, Tween, CircleCollider2D, Collider } from 'cc';
import { BasicComponet } from '../../Init/Basic/BasicComponet';
import { GlobalConfig } from '../../Init/Config/GlobalConfig';
import { GlobalEnum } from '../../Init/Config/GlobalEnum';
import { GlobalTmpData } from '../../Init/Config/GlobalTmpData';
import { EventTypes } from '../../Init/Managers/EventTypes';
import { AudioSystem } from '../../Init/SystemAudio/AudioSystem';
import { StorageSystem } from '../../Init/SystemStorage/StorageSystem';
import { LevelDataTmp } from '../../Init/SystemStorage/StorageTemp';
import { UIEnum } from '../../Init/SystemUI/UIEnum';
import { UISystem } from '../../Init/SystemUI/UISystem';
import { clog } from '../../Init/Tools/ColorLog';
import GlobalPool from '../../Init/Tools/GlobalPool';
import { SubBorn, Zombie2D } from './Zombie2D';
const { ccclass, property } = _decorator;

@ccclass('TouchPlayer')
export class TouchPlayer extends BasicComponet {
    protected _lvData: LevelDataTmp = null;
    protected _radius = 15;
    //
    protected _body: RigidBody2D = null;
    protected _collider: CircleCollider2D = null;

    protected _lineDirec = v2();
    //状态
    private _isRun = false;
    private _isOver = false;
    //相机跟随
    private _camerPos3d = v3();
    private _cameraOffset = v3();
    //--------控制属性
    private _moveSpd = GlobalConfig.Player.moveSpd;

    //强制移动状态
    private _isForthState = false;
    //---
    //草丛记录
    private _grassRecs: { [zombieUuid: string]: string[] } = {};

    // #region ---------流程------------
    protected onEvents() {
        //
        this.on(EventTypes.TouchEvents.TouchStart, this.onTouchStart, this);
        this.on(EventTypes.TouchEvents.TouchMove, this.onTouchMove, this);
        this.on(EventTypes.TouchEvents.TouchEnd, this.onTouchEnd, this);
        //
        this.on(EventTypes.GameEvents.GameRun, this.onGameRun, this);
        this.on(EventTypes.GameEvents.GameOver, this.onGameOver, this);
        //
        this.on(EventTypes.RoleEvents.CreateZombie, this.onCreateZombie, this);
        this.on(EventTypes.RoleEvents.ZombieDeath, this.onZombieDeath, this);
        this.on(EventTypes.RoleEvents.ByAtk, this.onByAtk, this);
        this.on(EventTypes.EnemyEvents.CheckClosetZombie, this.onCheckClosetZombie, this);
        this.on(EventTypes.EnemyEvents.CheckZombies, this.onCheckZombies, this);
        //
        this.on(EventTypes.RoleEvents.CanceResurgence, this.onCanceResurgence, this);
        this.on(EventTypes.RoleEvents.Resurgence, this.onResurgence, this);
        //
        this.on(EventTypes.RoleEvents.FindEnemy, this.onFindEnemy, this);
        //
        this.on(EventTypes.RoleEvents.SetZombieHideState, this.onSetZombieHideState, this);
        //
        this.on(EventTypes.RoleEvents.AddZombies, this.onAddAwardZombie, this);
        this.on(EventTypes.RoleEvents.AddAwardHP, this.onAddAwardHP, this);
        this.on(EventTypes.RoleEvents.AddProtected, this.onAddProtected, this);
        //
        this.on(EventTypes.GameEvents.GamePause, this.onGamePause, this);
        //
        this.on(EventTypes.CurLevelEvents.EnterParty, this.onEnterParty, this);
        this.on(EventTypes.CurLevelEvents.PartyFinished, this.onPartyFinished, this);
        this.on(EventTypes.CurLevelEvents.CombCoffiAnimFinished, this.onCombCoffiAnimFinished, this);
        this.on(EventTypes.RoleEvents.JumpCoverFinished, this.onJumpCoverFinished, this);
    }

    public initSub() {
        this.initSubRoles();
    }

    public reset() {
        this._isRun = false;
        this._isOver = false;
        this._body.linearVelocity = v2();

        this._lastZombie = null;
        this._lineDirec.set(0, 0);
        this._grassRecs = {};
        this._cameraOffset.set(0, 0, 0);
        this._isForthState = false;
        this._collider.sensor = false;
        this._collider.apply();
        this.resetSubRoles();
    }

    protected setData(d: { pos: Vec3, parent: Node, lvData }) {
        this.node.parent = d.parent;
        this.node.setPosition(d.pos);

        this._lvData = d.lvData;
        this._body = this.node.getComponent(RigidBody2D);
        this._body[GlobalEnum.ExtralProp.addLineVec] = v3();
        this._collider = this.node.getComponent(CircleCollider2D);
        this._collider.sensor = false;
        this._collider.apply();

        this.setSubRolesData();
        //设置相机位置
        this.recorderWpos();
        this._camerPos3d.set(GlobalTmpData.Player.lpos3D);
        //
        let sp = this.node.getComponent(Sprite);
        if (sp) {
            sp.enabled = GlobalConfig.isShow2dCollider;
        }

        //角色初始化完成
        this.emit(EventTypes.RoleEvents.LoadFinish);

        //设置移动属性
        let data = StorageSystem.getData();
        this._moveSpd = GlobalConfig.RolePropCfg.getMoveSpdByLv(data.userAssets.props.moveSpdLv);
    }

    public update(dt) {
        //首页时
        if (!this._isRun) {
            this.moveSubRoles(dt);
        }
    }

    public customUpdate(dt) {
        dt *= GlobalTmpData.timeScale;
        if (!this._isRun) return;
        this.moveSubRoles(dt);
        //记录数据
        this.recorderWpos();
        this.moveTarget(dt);
        this.checkMarks(dt);
    }

    // #endregion

    // #region -----------触摸事件----------
    private _subV2 = v2();
    private _startPos = v2();

    protected onTouchStart(stp: Vec2) {
        if (this._isOver || GlobalTmpData.Game.isGamePause) return;
        this._startPos.set(stp);
    }
    protected onTouchMove(pre: Vec2, cur: Vec2) {
        if (this._isOver || GlobalTmpData.Game.isGamePause) return;
        //计算出的速度
        this._subV2.set(cur).subtract(this._startPos);
        this._subV2.normalize();
        this._lineDirec.set(this._subV2);
    }

    protected onTouchEnd(stp: Vec2, cur: Vec2) {
        if (this._isOver) return;
        //停止移动 
        this._lineDirec.set(0);

        // this.onGameResume();
    }
    // #endregion

    // #region -----------TouchPlayer 触摸点--------
    private _spdData = { t: GlobalEnum.Effect2DType.GetSpdUp, p: Vec3.ZERO, delay: 1, isOne: true }
    //最后一只僵尸
    private _lastZombie: Zombie2D = null;
    private _tmpLineV = v2();

    /**移动触摸刚体 */
    protected moveTarget(dt) {
        if (this._isForthState) return;
        //
        if (!this.checkRunRoles()) {
            this._body.linearVelocity = this._tmpLineV.set(0, 0);
        } else {
            let extralSpdRate = (GlobalTmpData.BuffRecs[GlobalEnum.BuffType.AddSpeed] &&
                GlobalTmpData.BuffRecs[GlobalEnum.BuffType.AddSpeed].num) || 0;

            //通道加速
            if (GlobalTmpData.PartyInfo.isInPass && !GlobalTmpData.PartyInfo.isEnter) {
                // this.emit(EventTypes.EffectEvents.showUIEffect, this._spdData);
                extralSpdRate += clamp(GlobalConfig.Player.PassSpdRate - 1, 0, 10);
            }

            //多只时 计算碰撞
            this._tmpLineV.set(this._lineDirec).multiplyScalar(this._moveSpd * (1 + extralSpdRate) * dt * 60);
            this._tmpLineV.add(this._body[GlobalEnum.ExtralProp.addLineVec]);
            this._body.linearVelocity = this._tmpLineV;

            if (!this._lastZombie) {
                //多只僵尸存在时 相机跟随touch位置
                this.tmpV3.set(GlobalTmpData.Player.lpos3D);
            } else {
                //一只 则跟随僵尸
                this.tmpV3.set(this._lastZombie.node.position);
                this.tmpV3.set(this.tmpV3.x, 0, -this.tmpV3.y).multiplyScalar(GlobalConfig.Scale2DTo3D);
            }
            this._camerPos3d.lerp(this.tmpV3, 0.4);
        }
    }
    //检测标记点
    private checkMarks(dt) {
        const partMarkZ = -GlobalTmpData.PartyInfo.partyMark.z / GlobalConfig.Scale2DTo3D;
        //检测 通道 
        GlobalTmpData.PartyInfo.isInPass =
            this.node.position.y < partMarkZ && this.node.position.y > GlobalTmpData.EndArea.p2d.y;
        if (!GlobalTmpData.PartyInfo.isFirstInPass && GlobalTmpData.PartyInfo.isInPass) {
            GlobalTmpData.PartyInfo.isInPass = true;
            this.emit(EventTypes.CurLevelEvents.EnterPass);
        }

        //进入大逃杀模式
        if (!GlobalTmpData.PartyInfo.isEnter && this.node.position.y >= partMarkZ) {
            GlobalTmpData.PartyInfo.isEnter = true;
            this.emit(EventTypes.CurLevelEvents.EnterParty);
        }
    }

    //记录数据
    private recorderWpos() {
        const lp = this.node.position;
        const wp = this.node.worldPosition;
        GlobalTmpData.Player.lpos2D.set(lp);
        GlobalTmpData.Player.lpos3D.set(lp.x, 0, -lp.y).multiplyScalar(GlobalConfig.Scale2DTo3D);
        GlobalTmpData.Player.wpos2D.set(wp);
        GlobalTmpData.Player.wpos3D.set(wp.x, 0, -wp.y).multiplyScalar(GlobalConfig.Scale2DTo3D);

        //引导关卡跟随位置    
        if (GlobalTmpData.Game.isGuideLv) {
            let zombie: Zombie2D;
            for (const key in this._roles) {
                zombie = this._roles[key];
                break;
            }
            if (zombie) {
                const lp = zombie.node.position;
                GlobalTmpData.Player.guideLpos3d.set(lp.x, 0, -lp.y).multiplyScalar(GlobalConfig.Scale2DTo3D);;
            }
        }
    }

    /**判断是否有可控制移动的僵尸 */
    private checkRunRoles() {
        let num = 0;
        this._lastZombie = null;
        for (const key in this._roles) {
            if (this._roles[key]._curState == GlobalEnum.ZombieState.Idle ||
                this._roles[key]._curState == GlobalEnum.ZombieState.Run) {
                this._lastZombie = this._roles[key];
                num++;
            }
        }
        this._lastZombie = num > 1 && this._lastZombie.node.active ? null : this._lastZombie;

        return num > 0;
    }
    tmpP = v3();
    //强制移动到跳跃点动画-派对最后逻辑
    private moveToJumpos(t = 1, cb) {
        //转2d坐标
        this.tmpV3.set(GlobalTmpData.PartyInfo.jumpPos).multiplyScalar(1 / GlobalConfig.Scale2DTo3D);

        this._tmpLineV.set(0, 0);
        this._body.linearVelocity = this._tmpLineV;
        //
        this._collider.sensor = true;
        this._collider.apply();

        Tween.stopAllByTarget(this.tmpP);
        this.tmpP.set(this.node.position);
        tween(this.tmpP).to(t, { x: this.tmpV3.x, y: -this.tmpV3.z }, {
            onUpdate: () => {
                this.node.setPosition(this.tmpP);
                this.tmpV3.set(GlobalTmpData.Player.lpos3D);
                this._camerPos3d.lerp(this.tmpV3, 0.4);
            }
        }).call(() => {
            cb && cb();
        }).start();
    }

    // #endregion  

    // #region -----------Zombie2D 僵尸--------------
    protected _roles: { [uuid: string]: Zombie2D } = {};
    protected _targetPosArr: { [id: number]: { isUsed: boolean, pos: Vec3 } } = {};
    protected _bornPos: Vec3 = v3();
    protected _jumpCoverRecs: { [uuid: string]: boolean } = {};

    protected initSubRoles() {
        for (const key in ZombiePosArr) {
            const p = ZombiePosArr[key];
            if (!this._targetPosArr[key]) {
                this._targetPosArr[key] = { isUsed: false, pos: v3() };
            }
            this._targetPosArr[key].isUsed = false;
            this._targetPosArr[key].pos.set(p.x, p.y, p.z).multiplyScalar(1.2);
        }
    }

    protected resetSubRoles() {
        //清除记录
        this.resetTargetPos();
        for (const key in this._roles) {
            this._roles[key].reset();
        }
        this._roles = {};
        this._jumpCoverRecs = {};
    }
    //创建初始数量的僵尸
    protected setSubRolesData() {
        //--获取出生点位置
        let recArr = this._lvData.models['fenmu']; //3D坐标
        if (recArr) {
            this._bornPos.set(0, 0, 0);
            this._bornPos.set(v3(recArr[0].p.x, -recArr[0].p.z, 0).multiplyScalar(1 / GlobalConfig.Scale2DTo3D));
            this._bornPos.x = 0;
        }
        //
        let numLv = StorageSystem.getData().userAssets.props.numLv;
        let n = GlobalConfig.RolePropCfg.getNumRateByLv(numLv);

        let lv = StorageSystem.getData().levelAssets.curLv;
        //引导关卡
        if (lv == 1) {
            let initP = v3(this._bornPos);
            // initP.y = -210;
            // // initP.y -= 30;
            for (let i = 0; i < n; i++) {
                this.createSubRole(initP, Vec3.ZERO, true, GlobalEnum.ZombieState.Born, { isGuideCrawl: true });
            }

        } else {
            for (let i = 0; i < n; i++) {
                this.createSubRole(null, this.node.position, false, GlobalEnum.ZombieState.Idle);
            }
        }
    }
    /**创建新的僵尸 */
    protected createSubRole(initPos?: Vec3, addPos?: Vec3, isCreateInLv = false, initState?, stateData?) {
        let p = v3();
        let targetPos = v3();

        targetPos.set(this.getTargetPos());

        let e = GlobalPool.get('zombie2d');
        // e.active = false;
        e.parent = this.node.parent;
        //僵尸初始位置
        if (initPos) {
            p.set(initPos);
        } else {
            p.set(targetPos);
            addPos && p.add(addPos);
        }

        e.setPosition(p);
        // e.active = true;
        let cmp = new Zombie2D(e, this.node, targetPos);
        cmp.init(isCreateInLv); //isCreateInLv: 出生后爬过去
        cmp.setInitState(initState, stateData);
        this._roles[e.uuid] = cmp;
        //同步到3d
        this.emit(EventTypes.Mapping3DEvents.SetRoles, cmp.mappingProps);
        return cmp;
    }

    protected moveSubRoles(dt) {
        GlobalTmpData.Player.curRoleNum = 0;
        GlobalTmpData.Player.curCtrlNum = 0;

        for (const key in this._roles) {
            const role = this._roles[key];
            if (role && role.node.active) {
                role.update(dt);
                //统计
                GlobalTmpData.Player.curRoleNum++;
                if (role._curState == GlobalEnum.ZombieState.Idle ||
                    role._curState == GlobalEnum.ZombieState.Run ||
                    role._curState == GlobalEnum.ZombieState.Crawl) {
                    GlobalTmpData.Player.curCtrlNum++;
                }
            } else {
                delete this._roles[key];
            }
        }
    }

    protected resetTargetPos() {
        for (const key in this._targetPosArr) {
            const rec = this._targetPosArr[key];
            if (rec) {
                rec.isUsed = false;
            }
        }
    }

    /**获取新的 zombie目标跟随点 */
    protected getTargetPos() {
        for (const key in this._targetPosArr) {
            const rec = this._targetPosArr[key];
            if (!rec.isUsed) {
                rec.isUsed = true;
                return rec.pos;
            }
        }
        clog.warn('僵尸数量超出上限');
        return v3();
    }
    // #endregion

    // #region -----------自定义事件-----------
    private tmpV3 = v3();
    protected onGameOver() {
        let sum = 0;
        for (const key in this._roles) {
            if (this._roles[key].hp > 0) {
                sum++;
            }
        }
        GlobalTmpData.Player.survive = sum;
        this._isOver = true;
    }
    // 游戏开始运行
    protected onGameRun() {
        // console.log('Player Run');
        this._isRun = true;
        // //设置相机跟随        
        this.emit(EventTypes.CameraEvents.SetFollowPos, this._camerPos3d);
        //
        //非引导关卡 检测是否有处于born状态的僵尸->直接切换到下一个状态
        if (!GlobalTmpData.Game.isGuideLv) {
            for (const key in this._roles) {
                const role = this._roles[key];
                if (role._curState == GlobalEnum.ZombieState.Born) {
                    (role._stateRecs[role._curState] as SubBorn).bornFinished();
                }
            }
        }
    }

    protected onGamePause() {
        //停止移动         
        this._body.linearVelocity = this._tmpLineV.set(0, 0);
        for (const key in this._roles) {
            const role = this._roles[key];
            if (role && role.body) {
                role.body.linearVelocity = this._tmpLineV.set(0, 0);
            }
        }
    }

    protected onGameResume() {
        if (!GlobalTmpData.Game.isGamePause) return;
        this.emit(EventTypes.GameEvents.GameResume);
        AudioSystem.resumeBGM();
    }

    protected onEnterParty() {
        //拉高镜头
        Tween.stopAllByTarget(this._cameraOffset);
        this._cameraOffset.set(0, 0, 0);
        tween(this._cameraOffset).to(0.5, { y: 5, z: 3 }, {
            easing: 'sineInOut', onUpdate: () => {
                this.tmpP.set(this._cameraOffset).add(GlobalConfig.Camera.lvCamraPos);
                this.emit(EventTypes.CameraEvents.SetCameraSelfPos, this.tmpP);
            }
        },).start();

    }
    protected onPartyFinished() {
        this._isOver = true;
        // 强制移动到固定点   
        this._isForthState = true;
        //转2d
        this.tmpP.set(GlobalTmpData.PartyInfo.coffinPos).multiplyScalar(1 / GlobalConfig.Scale2DTo3D);
        this.tmpP.set(this.tmpP.x, -this.tmpP.z, 0).subtract(this.node.position);
        let dist = this.tmpP.length() * GlobalConfig.Scale2DTo3D;
        let t = dist / (this._moveSpd * 2);
        this.moveToJumpos(t, () => {
            this.emit(EventTypes.CurLevelEvents.ShowCombCoffiAnim);
        })
    }

    //游戏中/首页 生成新的僵尸
    protected onCreateZombie(p: Vec3, isCreateInLv) {
        //获取初始位置
        if (!GlobalTmpData.Game.isGameRun) {
            //首页创建
            let initPos = this._bornPos || v3(0, 0, -240);
            //随机位置
            initPos.x = Math.random() * 300 - 150;

            this.createSubRole(initPos, Vec3.ZERO, true, GlobalEnum.ZombieState.Born);
        } else {
            this.createSubRole(p, Vec3.ZERO, isCreateInLv,);
        }
    }

    //僵尸死亡之后-需要重新阵型
    protected onZombieDeath(cmp: Zombie2D) {
        this.resetTargetPos();
        //检测剩余个数
        let num = 0;
        for (const key in this._roles) {
            if (this._roles[key] != cmp && this._roles[key].node.active) {
                num++;
                //重新排列                 
                this._roles[key].targetPos.set(this.getTargetPos());
            }
        }
        if (num <= 0) {
            //复活
            UISystem.showUI(UIEnum.ResurgenceLvupUI);
        }
        // console.log('剩余:', num)
    }
    //受到攻击
    protected onByAtk(d: { uuid: string, atk: number, cb: Function }) {
        if (this._roles[d.uuid] && this._roles[d.uuid].hp > 0) {
            this._roles[d.uuid].byAtk(d.atk);
            d.cb && d.cb(true);
        } else {
            d.cb && d.cb(false);
        }
    }
    //检测最近的一只僵尸
    protected onCheckClosetZombie(d: { wp: Vec3, r: number, outZombie: Zombie2D }) {
        let minDist = 9999;
        for (const key in this._roles) {
            const zombie = this._roles[key];
            if (zombie && !zombie.isHide && zombie.hp > 0) {
                this.tmpV3.set(zombie.node.worldPosition);
                if (this.tmpV3.y >= d.wp.y - d.r && this.tmpV3.y <= d.wp.y + d.r &&
                    this.tmpV3.x >= d.wp.x - d.r && this.tmpV3.x <= d.wp.x + d.r) {
                    const dist = this.tmpV3.subtract(d.wp).length();
                    if (dist <= d.r && dist < minDist) {
                        d.outZombie = zombie;
                        minDist = dist;
                        break;
                    }
                }
            }
        }
    }
    //检测附近所有的僵尸
    protected onCheckZombies(d: { wp: Vec3, r: number, outZombies: Zombie2D[] }) {
        for (const key in this._roles) {
            const zombie = this._roles[key];
            if (zombie && zombie.hp > 0) {
                this.tmpV3.set(zombie.node.worldPosition);
                if (this.tmpV3.y >= d.wp.y - d.r && this.tmpV3.y <= d.wp.y + d.r &&
                    this.tmpV3.x >= d.wp.x - d.r && this.tmpV3.x <= d.wp.x + d.r) {
                    const dist = this.tmpV3.subtract(d.wp).length();
                    if (dist <= d.r) {
                        d.outZombies.push(zombie);
                    }
                }
            }
        }
    }
    protected _lastEmojiTime = 0;
    //发现敌方
    protected onFindEnemy() {
        //控制显示间隔
        let curt = Date.now();
        if (curt - this._lastEmojiTime < 2000) {
            return;
        }
        this._lastEmojiTime = curt;
        //概率显示表情
        let r = GlobalTmpData.Game.isGuideLv ? 0 : Math.random();
        // r = 0;//test
        if (r < 0.6) {
            let t = Math.random() > 0.5 ? GlobalEnum.EmojiTypes.Zombie_love : GlobalEnum.EmojiTypes.Zombie_vomit;
            let target = this._lastZombie ? this._lastZombie.node : this.node;
            this.emit(EventTypes.EffectEvents.ShowEmoji, { t: t, target: target });
        }
    }
    //复活
    protected onResurgence() {
        let numLv = StorageSystem.getData().userAssets.props.numLv;
        let n = GlobalConfig.RolePropCfg.getNumRateByLv(numLv);
        this.resetTargetPos();

        for (let i = 0; i < n; i++) {
            this.createSubRole(null, this.node.position);
        }
        // 进入保护时间
        for (const key in this._roles) {
            const e = this._roles[key];
            e.enterProtected(GlobalConfig.Player.protectedTime);
        }
    }
    //取消复活
    protected onCanceResurgence() {
        this.emit(EventTypes.GameEvents.GameOver, false);
    }
    //显隐僵尸
    protected onSetZombieHideState(d: { cldId: string, zombieId: string, isHide: boolean }) {
        if (!this._grassRecs[d.zombieId]) {
            this._grassRecs[d.zombieId] = [];
        }
        //草丛id
        let grassIndex = this._grassRecs[d.zombieId].indexOf(d.cldId);
        //出草
        if (!d.isHide && grassIndex >= 0) {
            this._grassRecs[d.zombieId].splice(grassIndex, 1);
        }
        //进草
        if (d.isHide && grassIndex <= 0) {
            this._grassRecs[d.zombieId].push(d.cldId);
        }
        //判断是否在草丛中
        let isHide = this._grassRecs[d.zombieId].length > 0;
        for (const key in this._roles) {
            if (key == d.zombieId) {
                const e = this._roles[key];
                e.setHide(isHide);
                break;
            }
        }
    }
    //增加奖励僵尸
    protected onAddAwardZombie(num: number) {
        for (let i = 0; i < num; i++) {
            this.onCreateZombie(GlobalTmpData.Player.wpos3D, false);
        }
    }
    //恢复血量
    protected onAddAwardHP(num: number) {
        for (const key in this._roles) {
            const e = this._roles[key];
            e && e.addHPByRate(num);
        }
    }
    //保护罩
    protected onAddProtected(delay: number) {
        for (const key in this._roles) {
            const e = this._roles[key];
            e && e.enterProtected(delay);
        }
    }
    //派对动画结束之后 角色进入胜利状态
    protected onCombCoffiAnimFinished() {
        // let maxTime = 5;
        // for (const key in this._roles) {
        //     const role = this._roles[key];
        //     let time = Math.random() * maxTime * 1000;
        //     this._jumpCoverRecs[role.node.uuid] = false;
        //     let tid = setTimeout(() => {
        //         clearTimeout(tid);
        //         role.changeState(GlobalEnum.ZombieState.Win);
        //     }, time);
        // }
        let time = 0;
        let n = 0;
        for (const key in this._roles) {
            const role = this._roles[key];
            this._jumpCoverRecs[role.node.uuid] = false;
            time = n * 100;
            let tid = setTimeout(() => {
                clearTimeout(tid);
                role.changeState(GlobalEnum.ZombieState.Win);
            }, time);
            n++;
        }
    }

    //最终跳跃结束
    protected onJumpCoverFinished(uuid: string) {
        this._jumpCoverRecs[uuid] = true;
        let isFinish = true;
        //胜利
        for (const key in this._jumpCoverRecs) {
            isFinish = isFinish && this._jumpCoverRecs[key];
        }
        if (isFinish) {
            setTimeout(() => {
                this.emit(EventTypes.GameEvents.GameOver, true);

            }, 1000);
        }
    }
    // #endregion

}


export const ZombiePosArr = [{ "x": 0, "y": 0, "z": 0 }, { "x": 30, "y": 0, "z": 0 }, { "x": 15, "y": -30, "z": 0 }, { "x": -15, "y": -30, "z": 0 }, { "x": -30, "y": 0, "z": 0 }, { "x": -15, "y": 30, "z": 0 }, { "x": 15, "y": 30, "z": 0 }, { "x": 45, "y": 30, "z": 0 }, { "x": 60, "y": 0, "z": 0 }, { "x": 45, "y": -30, "z": 0 }, { "x": 30, "y": -60, "z": 0 }, { "x": 0, "y": -60, "z": 0 }, { "x": -30, "y": -60, "z": 0 }, { "x": -45, "y": -30, "z": 0 }, { "x": -60, "y": 0, "z": 0 }, { "x": -45, "y": 30, "z": 0 }, { "x": -30, "y": 60, "z": 0 }, { "x": 0, "y": 60, "z": 0 }, { "x": 30, "y": 60, "z": 0 }, { "x": 60, "y": 60, "z": 0 }, { "x": 75, "y": 30, "z": 0 }, { "x": 90, "y": 0, "z": 0 }, { "x": 75, "y": -30, "z": 0 }, { "x": 60, "y": -60, "z": 0 }, { "x": 45, "y": -90, "z": 0 }, { "x": 15, "y": -90, "z": 0 }, { "x": -15, "y": -90, "z": 0 }, { "x": -45, "y": -90, "z": 0 }, { "x": -60, "y": -60, "z": 0 }, { "x": -75, "y": -30, "z": 0 }, { "x": -90, "y": 0, "z": 0 }, { "x": -75, "y": 30, "z": 0 }, { "x": -60, "y": 60, "z": 0 }, { "x": -45, "y": 90, "z": 0 }, { "x": -15, "y": 90, "z": 0 }, { "x": 15, "y": 90, "z": 0 }, { "x": 45, "y": 90, "z": 0 }, { "x": 75, "y": 90, "z": 0 }, { "x": 90, "y": 60, "z": 0 }, { "x": 105, "y": 30, "z": 0 }, { "x": 120, "y": 0, "z": 0 }, { "x": 105, "y": -30, "z": 0 }, { "x": 90, "y": -60, "z": 0 }, { "x": 75, "y": -90, "z": 0 }, { "x": 60, "y": -120, "z": 0 }, { "x": 30, "y": -120, "z": 0 }, { "x": 0, "y": -120, "z": 0 }, { "x": -30, "y": -120, "z": 0 }, { "x": -60, "y": -120, "z": 0 }, { "x": -75, "y": -90, "z": 0 }, { "x": -90, "y": -60, "z": 0 }, { "x": -105, "y": -30, "z": 0 }, { "x": -120, "y": 0, "z": 0 }, { "x": -105, "y": 30, "z": 0 }, { "x": -90, "y": 60, "z": 0 }, { "x": -75, "y": 90, "z": 0 }, { "x": -60, "y": 120, "z": 0 }, { "x": -30, "y": 120, "z": 0 }, { "x": 0, "y": 120, "z": 0 }, { "x": 30, "y": 120, "z": 0 }, { "x": 60, "y": 120, "z": 0 }, { "x": 90, "y": 120, "z": 0 }, { "x": 105, "y": 90, "z": 0 }, { "x": 120, "y": 60, "z": 0 }, { "x": 135, "y": 30, "z": 0 }, { "x": 150, "y": 0, "z": 0 }, { "x": 135, "y": -30, "z": 0 }, { "x": 120, "y": -60, "z": 0 }, { "x": 105, "y": -90, "z": 0 }, { "x": 90, "y": -120, "z": 0 }, { "x": 75, "y": -150, "z": 0 }, { "x": 45, "y": -150, "z": 0 }, { "x": 15, "y": -150, "z": 0 }, { "x": -15, "y": -150, "z": 0 }, { "x": -45, "y": -150, "z": 0 }, { "x": -75, "y": -150, "z": 0 }, { "x": -90, "y": -120, "z": 0 }, { "x": -105, "y": -90, "z": 0 }, { "x": -120, "y": -60, "z": 0 }, { "x": -135, "y": -30, "z": 0 }, { "x": -150, "y": 0, "z": 0 }, { "x": -135, "y": 30, "z": 0 }, { "x": -120, "y": 60, "z": 0 }, { "x": -105, "y": 90, "z": 0 }, { "x": -90, "y": 120, "z": 0 }, { "x": -75, "y": 150, "z": 0 }, { "x": -45, "y": 150, "z": 0 }, { "x": -15, "y": 150, "z": 0 }, { "x": 15, "y": 150, "z": 0 }, { "x": 45, "y": 150, "z": 0 }, { "x": 75, "y": 150, "z": 0 }, { "x": 105, "y": 150, "z": 0 }, { "x": 120, "y": 120, "z": 0 }, { "x": 135, "y": 90, "z": 0 }, { "x": 150, "y": 60, "z": 0 }, { "x": 165, "y": 30, "z": 0 }, { "x": 180, "y": 0, "z": 0 }, { "x": 165, "y": -30, "z": 0 }, { "x": 150, "y": -60, "z": 0 }, { "x": 135, "y": -90, "z": 0 }, { "x": 120, "y": -120, "z": 0 }, { "x": 105, "y": -150, "z": 0 }, { "x": 90, "y": -180, "z": 0 }, { "x": 60, "y": -180, "z": 0 }, { "x": 30, "y": -180, "z": 0 }, { "x": 0, "y": -180, "z": 0 }, { "x": -30, "y": -180, "z": 0 }, { "x": -60, "y": -180, "z": 0 }, { "x": -90, "y": -180, "z": 0 }, { "x": -105, "y": -150, "z": 0 }, { "x": -120, "y": -120, "z": 0 }, { "x": -135, "y": -90, "z": 0 }, { "x": -150, "y": -60, "z": 0 }, { "x": -165, "y": -30, "z": 0 }, { "x": -180, "y": 0, "z": 0 }, { "x": -165, "y": 30, "z": 0 }, { "x": -150, "y": 60, "z": 0 }, { "x": -135, "y": 90, "z": 0 }, { "x": -120, "y": 120, "z": 0 }, { "x": -105, "y": 150, "z": 0 }, { "x": -90, "y": 180, "z": 0 }, { "x": -60, "y": 180, "z": 0 }, { "x": -30, "y": 180, "z": 0 }, { "x": 0, "y": 180, "z": 0 }, { "x": 30, "y": 180, "z": 0 }, { "x": 60, "y": 180, "z": 0 }, { "x": 90, "y": 180, "z": 0 }]
